package top.eggcode.setup.config.shiro;

import lombok.RequiredArgsConstructor;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;
import top.eggcode.common.auth.SessionTokenUtil;
import top.eggcode.common.error.ApplicationException;
import top.eggcode.common.error.TokenRefreshException;
import top.eggcode.common.model.SessionToken;
import top.eggcode.system.modules.user.model.AccountEntity;
import top.eggcode.system.modules.user.service.AccountServiceImpl;
import top.eggcode.system.modules.user.service.UserServiceImpl;

import java.util.Optional;

/**
 * Title: Token身份
 * Description: TODO
 * Date: 2021/4/11 22:39
 *
 * @author JiaQi Ding
 * @version 1.0
 */
@Component
@RequiredArgsConstructor
public class TokenRealm extends AuthorizingRealm {

    private final AccountServiceImpl accountService;

    private final UserServiceImpl userService;

    /**
     * 重写令牌类型的验证
     *
     * @param token 令牌
     * @return 结果
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof SessionToken;
    }

    /**
     * 获取用户权限
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String) principalCollection.getPrimaryPrincipal();
        Optional<AccountEntity> box = accountService.findByUsername(username);
        if (!box.isPresent()) {
            throw new ApplicationException("找不到账户信息");
        }
        AccountEntity account = box.get();

        SimpleAuthorizationInfo authorization = new SimpleAuthorizationInfo();
        // 绑定角色码
        authorization.addRoles(userService.getRoleCodeList(account.getUsername()));
        // 绑定操作码
        authorization.addStringPermissions(
                userService.getPowerCodeList(account.getUsername())
        );
        return authorization;
    }

    /**
     * 获取用户身份
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        // 获取当前用户的登录凭证
        String token = (String) authenticationToken.getCredentials();

        // token 过期
        if (SessionTokenUtil.overdue(token)) {
            throw new ExpiredCredentialsException("token 已经过期");
        }

        // token 需要刷新
        if (SessionTokenUtil.requiredRefresh(token)) {
            throw new TokenRefreshException("token 需要刷新");
        }

        // 无效token
        if (!SessionTokenUtil.verify(token)) {
            throw new IncorrectCredentialsException("无效 token");
        }

        return new SimpleAuthenticationInfo(
                SessionTokenUtil.getUsername(token),
                token,
                getName());
    }
}
